#include "line.h"
#include "Fitting/gauss/FittingLinePCA.h"
namespace  ELEMENT {
    Line::Line():Element()
    {
        type = ElementType::Line;
    }

    void Line::setGeometry(Fitting::Line &l)
    {
        line=l;


        QOpenGLVertexArrayObject::Binder bind(&VAO);
        EBO.create();
        EBO.bind();
        EBO.allocate(index.data(), sizeof(GLint)*index.size());

        VBO.create();       //生成VBO对象
        VBO.bind();         //将VBO绑定到当前的顶点缓冲对象（QOpenGLBuffer::VertexBuffer）中
        //将顶点数据分配到VBO中，第一个参数为数据指针，第二个参数为数据的字节长度
        VBO.allocate(vertices.data(), sizeof(Eigen::Vector3d)*vertices.size());
        glVertexAttribPointer(0, 3, GL_DOUBLE, GL_FALSE, sizeof(Eigen::Vector3d), (void*)0);
        glEnableVertexAttribArray(0);
    }

    bool Line::fit(const std::vector<Point> &points)
    {
        double err = Gauss::FittingPCA(points, line);
        if(err<0) {
            return false;
        }

        qDebug()<<err;
        qDebug()<<line.BasePoint.x()<<line.BasePoint.y()<<line.BasePoint.z();
        qDebug()<<line.Orient.x()<<line.Orient.y()<<line.Orient.z();

        // 计算长度
        double lmax=0, lmin=0;
        for(auto &p: points) {
            double l = (p-line.BasePoint).dot(line.Orient);
            if(l>lmax)lmax=l;
            if(l<lmin)lmin=l;
        }
        len = lmax-lmin;

        vertices.resize(2);
        vertices[0]=line.BasePoint+line.Orient*lmax;
        vertices[1]=line.BasePoint+line.Orient*lmin;
        index.resize(vertices.size());
        for(int i=0;i<index.size();++i) index[i]=i;
        return true;
    }

    void Line::Draw(QOpenGLShaderProgram &shader)
    {
        shader.bind();
        shader.setUniformValue("userColor",QVector4D(0.0f, 0.5f, 0.5f, 1.0f));
        QOpenGLVertexArrayObject::Binder bind(&VAO);
        glLineWidth(3);
        glDrawElements(GL_LINES, index.size(), GL_UNSIGNED_INT, 0);
    }

    QString Line::Info()
    {
        QString info("类型：直线\n长度：%1\n中心点：%2 %3 %4\n法向：%5 %6 %7");
        return info.arg(len)
                .arg(line.BasePoint.x()).arg(line.BasePoint.y()).arg(line.BasePoint.z())
                .arg(line.Orient.x()).arg(line.Orient.y()).arg(line.Orient.z());
    }

}
